/*
 * Copyright 2017 Google, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License")
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package com.netflix.spinnaker.halyard.deploy.spinnaker.v1.profile;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.netflix.spinnaker.halyard.config.config.v1.HalconfigDirectoryStructure;
import com.netflix.spinnaker.halyard.config.model.v1.node.DeploymentConfiguration;
import com.netflix.spinnaker.halyard.config.model.v1.node.Node;
import com.netflix.spinnaker.halyard.deploy.services.v1.ArtifactService;
import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.SpinnakerArtifact;
import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.SpinnakerRuntimeSettings;
import org.springframework.beans.factory.annotation.Autowired;
import org.yaml.snakeyaml.Yaml;

import java.util.List;
import java.util.Map;

abstract public class ProfileFactory {
  @Autowired
  private ArtifactService artifactService;

  @Autowired
  private HalconfigDirectoryStructure halconfigDirectoryStructure;

  @Autowired
  private Yaml yamlParser;

  @Autowired
  private ObjectMapper strictObjectMapper;

  protected boolean showEditWarning() {
    return true;
  }

  protected ArtifactService getArtifactService() {
    return artifactService;
  }

  public Profile getProfile(String name, String outputFile, DeploymentConfiguration deploymentConfiguration, SpinnakerRuntimeSettings endpoints) {
    String deploymentName = deploymentConfiguration.getName();
    String version = getArtifactService().getArtifactVersion(deploymentName, getArtifact());
    Profile result = getBaseProfile(name, version, outputFile);
    setProfile(result, deploymentConfiguration, endpoints);
    if (showEditWarning()) {
      result.preppendContents(getEditWarning());
    }

    return result;
  }

  abstract protected void setProfile(Profile profile, DeploymentConfiguration deploymentConfiguration, SpinnakerRuntimeSettings endpoints);
  abstract protected Profile getBaseProfile(String name, String version, String outputFile);

  abstract public SpinnakerArtifact getArtifact();

  abstract protected String commentPrefix();

  private String getEditWarning() {
    return commentPrefix() + "WARNING\n" +
        commentPrefix() + "This file was autogenerated, and _will_ be overwritten by Halyard.\n" +
        commentPrefix() + "Any edits you make here _will_ be lost.\n";
  }

  /**
   * @param node is the node to find required files in.
   * @param deploymentName is the current deployment of Spinnaker being backed up.
   * @return the list of files required by the node to function.
   */
  protected List<String> backupRequiredFiles(Node node, String deploymentName) {
    return node.backupLocalFiles(halconfigDirectoryStructure.getStagingDependenciesPath(deploymentName).toString());
  }

  protected String yamlToString(Object o) {
    return yamlParser.dump(strictObjectMapper.convertValue(o, Map.class));
  }
}
